<?php

namespace app\service;

use app\model\BookType;
use app\model\BookType as BookTypeModel;
use app\model\BookTypeItem as BookTypeItemModel;
use app\model\Item as ItemModel;
use app\model\Catalog as CatalogModel;
use app\model\Member as MemberModel;
use app\model\Post as PostModel;
use support\Tree;
use support\UCenterService;
use teamones\filter\Enforcer;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Db;
use Throwable;

class Item
{
    // 用户权限id
    public $allMemberPerId = [];


    /**
     * 创建项目
     * @param $data
     * @return ItemModel|\think\Model|void
     * @throws \exception
     */
    public function create($data)
    {
        return ItemModel::create($data);
    }

    /**
     * 更新项目
     * @param $data
     * @return ItemModel|void
     * @throws \exception
     */
    public function update($data)
    {
        return ItemModel::update($data, ['id' => $data['id']]);
    }

    /**
     * 删除项目
     * @param $id
     * @return bool
     * @throws Throwable
     * @throws DbException
     */
    public function delete($id)
    {
        Db::startTrans();
        try {
            PostModel::where(['item_id' => $id])->delete();
            CatalogModel::where(['item_id' => $id])->delete();
            $isItemDel = ItemModel::where(['id' => $id])->delete();
            Db::commit();
            return $isItemDel;
        } catch (\Throwable $e) {
            Db::rollback();
            throw $e;
        }
    }

    /**
     * 查询项目
     * @param $currentUserId
     * @return array
     * @throws \exception
     */
    public function select($currentUserId)
    {
        $rows = ItemModel::where(["created_by" => $currentUserId])->select();
        return [
            'rows' => $rows->toArray()
        ];
    }

    /**
     * 查询出所有的目录
     * @param $id
     * @return array
     * @throws \exception
     */
    public function selectChild($id)
    {
        $catalogList = CatalogModel::where(['item_id' => $id])->order('number')->select()->toArray();
        $catalogPost = PostModel::where(['item_id' => $id])->order('number')->select()->toArray();
        $catalogPostGrouped = array_group_by($catalogPost, 'catalog_id');

        $catalogPostGrouped = array_map(function ($posts) {
            $posts = array_sort_by($posts, 'number');
            return $posts;
        }, $catalogPostGrouped);

        $t = new Tree("id", "parent_id", "catalog");
        $t->load($catalogList);
        $data = $t->DeepTree();
        if (is_array($data) && count($data) > 0) {
            $t->traverseTree($data, function (&$child) use (&$catalogPostGrouped) {
                if (isset($catalogPostGrouped[$child['id']])) {
                    $child['post'] = $catalogPostGrouped[$child['id']];
                } else {
                    $child['post'] = [];
                }
            });
        } else {
            $data = [];
        }

        $result['catalog'] = $data;

        // 追加第一层
        if (isset($catalogPostGrouped[0])) {
            $result['post'] = $catalogPostGrouped[0];
        } else {
            $result['post'] = [];
        }
        return $result;


    }

    /**
     * 查询指定目录下得所有文章和目录
     * @param $itemId
     * @param $catalogId
     * @param $tenantId
     * @return array|bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function selectCatalogAndPost($itemId, $catalogId, $tenantId)
    {
        $catalogList = CatalogModel::where(['item_id' => $itemId])->select()->toArray();
        $catalogPost = PostModel::where(['item_id' => $itemId])->order('number')->select()->toArray();
        $createdByIdList = array_column($catalogPost, 'created_by', 'created_by');
        // 填充用户信息
        if (count($createdByIdList) > 0) {
            $users = UCenterService::getInstance()->tenantUser->selectTenantUser([
                'param' => [
                    'filter' => [
                        'tenant_user.tenant_id' => $tenantId,
                        'tenant_user.user_id' => ['-in', implode(',', $createdByIdList)],
                    ],
                    'fields' => 'user.id,user.name,tenant_user.id,tenant_user.user_id,role.id,role.code,role.name,department.id,department.name'
                ]
            ]);
            $userMap = [];
            if (!empty($users['rows'])) {

                $users = array_map(function ($item) {
                    $item['user_id'] = $item['user']['id'];
                    return $item;
                }, $users['rows']);
                $userMap = array_column($users, null, 'user_id');
            }
            $catalogPost = array_map(function ($item) use (&$userMap) {
                $item['created_by'] = $userMap[$item['created_by']] ?? null;
                return $item;
            }, $catalogPost);
        }
        $catalogPostGrouped = array_group_by($catalogPost, 'catalog_id');

        $catalogPostGrouped = array_map(function ($posts) {
            $posts = array_sort_by($posts, 'number');
            return $posts;
        }, $catalogPostGrouped);
        $t = new Tree("id", "parent_id", "catalog");
        $t->load($catalogList);
        $data = $t->DeepTree($catalogId);
        if (is_array($data) && count($data) > 0) {
            $t->traverseTree($data, function (&$child) use (&$catalogPostGrouped) {
                if (isset($catalogPostGrouped[$child['id']])) {
                    $child['post'] = $catalogPostGrouped[$child['id']];
                } else {
                    $child['post'] = [];
                }
            });
        } else {
            $data = [];
        }

        // 追加第一层
        if (isset($catalogPostGrouped[$catalogId])) {
            $data['post'] = $catalogPostGrouped[$catalogId];
        } else {
            $data['post'] = [];
        }
        return $data;
    }

    /**
     * 查询单条
     * @param $post
     * @return array|\think\Model|null
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function findByName($post)
    {
        return ItemModel::where("name", $post['param']['filter']['name'])->where("tenant_id", $post['param']['filter']['tenant_id'])->find();
    }

    public function find($filter)
    {
        return ItemModel::where(Enforcer::parseWhere($filter))->find();
    }

    /**
     * 获取类型
     * @param $data
     * @return array|void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getBookType($data)
    {
        // 获取租户id
        $memberService = new Member();
        $memberData = $memberService->getTenantInfo($data['tenant_id'], 'id,created_by');
        // 租户创建人ID
        $type = $data['param']['filter']['type'] ?? '';
        // 平台型知识库不需要区分租户
        $where = ['type' => [BookTypeModel::PLATFORM_BOOK_TYPE, BookTypeModel::TENANT_BOOK_TYPE]];
        if ($type != BookTypeModel::PLATFORM_BOOK_TYPE) {
            $where = ['type' => [BookTypeModel::PLATFORM_BOOK_TYPE, BookTypeModel::TENANT_BOOK_TYPE], 'tenant_id' => $data['tenant_id']];
        }
        if (!empty($data['param']['filter']['id'])) {
            $where = ['type' => [BookTypeModel::PLATFORM_BOOK_TYPE, BookTypeModel::TENANT_BOOK_TYPE]];
        }
        $tenantCreatedById = $memberData['data']['created_by'] ?? 0;
        $bookModel = BookTypeModel::where(Enforcer::parseWhere($data['param']['filter']))
            ->where($where)
            ->select();
        if (!$bookModel->isEmpty()) {
            $bookData = $bookModel->toArray();
            // 团队知识库取角色权限
            if ($type != BookTypeModel::PLATFORM_BOOK_TYPE) {
                $knowledgeData = $this->getKnowledgeRole(array_column($bookData, 'id'), $data['user_id'], $tenantCreatedById, $data['tenant_id']);
            }
            $role = '';
            $platformRole = 'viewer'; // 平台权限
            if (!empty($data['param']['filter']['id'])) {
                $userRoleInfo = UCenterService::getInstance()->user->request('POST', 'user/get_my_user_info', [], []);
                $departmentInfo = array_column($userRoleInfo['department_info'], 'role_code');
                if (array_intersect(['super_admin', 'operators'], $departmentInfo)) {
                    $platformRole = 'super_admin';
                }
            }
            // 获取知识库下有权限的用户
            $perIdData = $this->getMemberPerId('knowledge', array_column($bookData, 'id'), $data['tenant_id']);
            // 获取用户信息
            $userInfo = $this->getUserInfo();
            // 绑定权限id与用户的关系
            $roleData = $this->execRole($perIdData, $userInfo);
            // 增加版本说明
            $lastVersionData = $this->getLastVersionList();
            if (empty($bookData)) {
                return [];
            }

            foreach ($bookData as $k => $v) {
                // 如果不是平台知识库,取普通知识库权限
                if ($v['type'] != BookTypeModel::PLATFORM_BOOK_TYPE) {
                    $role = $knowledgeData[$v['id']]['role'] ?? 'viewer';
                }
                // 如果是平台知识库,取当前用户角色在系统里的权限
                if ($v['type'] == BookTypeModel::PLATFORM_BOOK_TYPE) {
                    $role = $platformRole;
                }
                $bookData[$k]['role'] = $role;
                $bookData[$k]['role_info'] = $roleData[$v['id']] ?? [];
                $bookData[$k]['role_count'] = count($perIdData[$v['id']] ?? []);
                if ($v['type'] == BookTypeModel::PLATFORM_BOOK_TYPE && $v['id'] == BookType::VERSION_BOOK_TYPE) {
                    $bookData[$k]['version_info'] = $lastVersionData ?? null;
                }
            }
            return $bookData;
        }
    }

    /**
     * 版本说明,最细版本
     * @return PostModel|array|\think\Model|null
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getLastVersionList()
    {
        return PostModel::where(['book_type_id' => BookType::VERSION_BOOK_TYPE])->field('id,name,last_update_time')->order('id desc')->find();
    }

    /**
     * 获取被赋予权限ID
     * @param $type
     * @param $typeId
     * @param $tenantId
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getMemberPerId($type, $typeId, $tenantId): array
    {
        $memberModel = MemberModel::where(['type' => $type, 'type_id' => $typeId, 'tenant_id' => $tenantId])
            ->field('id,role,user_id,type_id')
            ->select();
        if ($memberModel->isEmpty()) {
            return [];
        }
        $typeIdArr = array_group_by($memberModel->toArray(), 'type_id');
        $returnData = [];
        if (!empty($typeIdArr)) {
            foreach ($typeIdArr as $k => $v) {
                $returnData[$k] = array_column($v, 'user_id');
            }
        }
        foreach ($returnData as $valUserId) {
            $needMemberUserInfo = array_slice($valUserId, 0, 3) ?? [];
            foreach ($needMemberUserInfo as $id) {
                $this->allMemberPerId[] = $id;
            }
        }
        return $returnData;
    }

    /**
     * 获取用户信息
     * @return array
     * @throws \exception
     */
    public function getUserInfo(): array
    {
        if (!empty($this->allMemberPerId)) {
            $memberService = new Member();
            $userData = $memberService->getUserInfo($this->allMemberPerId);
            return array_column($userData['data']['rows'], null, 'id');
        }
        return [];
    }


    /**
     * 处理角色信息
     * @param $perIdData
     * @param $userInfo
     * @return array
     */
    public function execRole($perIdData, $userInfo): array
    {
        $returnData = [];
        if (!empty($perIdData)) {
            foreach ($perIdData as $bookTypeId => $v) {
                $userData = [];
                $needData = array_slice($v, 0, 3) ?? [];
                foreach ($needData as $userV) {
                    if (empty($userInfo[$userV])) {
                        continue;
                    }
                    $userData[] = $userInfo[$userV];
                }
                $returnData[$bookTypeId] = $userData;
            }
        }
        return $returnData;
    }

    /**
     * 获取知识库角色
     * @param $typeId
     * @param $userId
     * @param $tenantId
     * @param $tenantCreatedById
     * @return array|void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getKnowledgeRole($typeId, $userId, $tenantCreatedById, $tenantId)
    {
        $memberModel = MemberModel::where(['type' => 'knowledge', 'user_id' => $userId, 'type_id' => $typeId, 'tenant_id' => $tenantId])
            ->field('role,type_id')
            ->select();
        // 判断是否超级用户
        if ($userId == $tenantCreatedById) {
            $data = [];
            foreach ($typeId as $v) {
                $data[$v]['role'] = 'super_admin';
            }
            return $data;
        }
        if (!$memberModel->isEmpty()) {
            return array_column($memberModel->toArray(), null, 'type_id');
        }
    }

    /**
     * 获取单个类型
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function findBookType($filter)
    {
        return BookTypeModel::where(Enforcer::parseWhere($filter))->find();
    }

    /**
     * 创建知识本项目
     * @param $data
     * @return ItemModel|\think\Model
     * @throws Throwable
     */
    public function createBookItem($data)
    {
        $itemData = $data;
        unset($itemData['book_type_id'], $itemData['item_type']);
        $itemType = $data['item_type'] ?? 'normal';
        $attribute = $data['attribute'] ?? ItemModel::PUBLIC_ATTR;
        try {
            $maxNumber = BookTypeItemModel::where(['book_type_id' => $data['book_type_id'], 'item_type' => $itemType])->max('number') + 1;
            Db::startTrans();
            $item = ItemModel::create($itemData);
            $bookTypeItem = [
                'item_id' => $item['id'],
                'book_type_id' => $data['book_type_id'],
                'number' => $maxNumber,
                'item_type' => $itemType,
                'attribute' => $attribute,
            ];
            BookTypeItemModel::create($bookTypeItem);
            Db::commit();
            return $item;
        } catch (\Throwable $e) {
            Db::rollback();
            throw $e;
        }


    }

    /**
     * @param $filter
     * @return bool
     * @throws \Throwable
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function deleteBookItem($filter)
    {
        $itemList = ItemModel::where(Enforcer::parseWhere($filter))->field('id')->select()->toArray();
        $count = false;
        if (empty($itemList)) {
            return $count;
        }
        $itemListId = array_column($itemList, 'id');
        Db::startTrans();
        try {
            PostModel::whereIn('item_id', $itemListId)->delete();
            CatalogModel::whereIn('item_id', $itemListId)->delete();
            ItemModel::whereIn('id', $itemListId)->delete();
            $count = BookTypeItemModel::whereIn('item_id', $itemListId)->delete();
            Db::commit();
            return $count;
        } catch (Throwable $e) {
            Db::rollback();
            throw $e;
        }
    }

    /**
     * 获取知识模板
     * @param $param
     * @return mixed
     * @throws \exception
     */
    public function getBookItem($param)
    {
        $field = $param['field'] ?? "item.id,item.name,icon,book_type_id,item_id,item_type,description";
        $page = $param['page'] ?? [1, 100];
        $order = $param['order'] ?? ['item_type' => 'desc', 'book_type_item.number' => 'asc', 'item.created' => 'desc'];
        return BookType::join('book_type_item', 'book_type.id = book_type_item.book_type_id')
            ->join('item', 'item.id = book_type_item.item_id')
            ->where(Enforcer::parseWhere($param['filter']))
            ->field($field)
            ->page($page[0], $page[1])
            ->order($order)
            ->select();
    }
}
